#include "map.h"
#include "qdebug.h"

#define OVER(a) ((a)<0 || (a)>5)
#define NEAR(a,b) ((a)-(b)<2 && (b)-(a)<2)
#define NOTSIDE(a) ((a)!=0 && (a)!=5)
extern double v[6][6];
bool Map::move(int si,int sj,int ei,int ej)
{
	//qDebug()<<"move";
	if(OVER(si) || OVER(sj) || OVER(ei) || OVER(ej) || (si==ei && sj==ej) || a[si][sj]==0)
		return 0;
	if(a[ei][ej]==0)
	{
		if(!NEAR(si,ei) || !NEAR(sj,ej))
			return 0;
		a[ei][ej]=a[si][sj];
		a[si][sj]=0;
		c[a[ei][ej]][0]=ei;
		c[a[ei][ej]][1]=ej;
		val[get(ei,ej)]+=v[ei][ej]-v[si][sj];
		return 1;
	}
	t[get(ei,ej)]--;
	if(get(ei,ej)!=get(si,sj) && a[ei][ej]!=0)
	{
		int i,j;
		if(NOTSIDE(si))
		{
			eat(si,sj,0,1,i,j);
			if(i==ei && j==ej)
			{
				val[get(si,sj)]+=v[ei][ej]-v[si][sj];
				val[get(ei,ej)]-=v[ei][ej];
				int r=(get(ei,ej)-1)*12+t[get(ei,ej)]+1;
				a[c[r][0]][c[r][1]]=a[ei][ej];
				c[a[ei][ej]][0]=c[r][0];
				c[a[ei][ej]][1]=c[r][1];
				a[ei][ej]=a[si][sj];
				c[a[ei][ej]][0]=ei;
				c[a[ei][ej]][1]=ej;
				a[si][sj]=0;
				return 1;
			}
			eat(si,sj,0,-1,i,j);
			if(i==ei && j==ej)
			{
				val[get(si,sj)]+=v[ei][ej]-v[si][sj];
				val[get(ei,ej)]-=v[ei][ej];
				int r=(get(ei,ej)-1)*12+t[get(ei,ej)]+1;
				a[c[r][0]][c[r][1]]=a[ei][ej];
				c[a[ei][ej]][0]=c[r][0];
				c[a[ei][ej]][1]=c[r][1];
				a[ei][ej]=a[si][sj];
				c[a[ei][ej]][0]=ei;
				c[a[ei][ej]][1]=ej;
				a[si][sj]=0;
				return 1;
			}
		}
		if(NOTSIDE(sj))
		{
			eat(si,sj,1,0,i,j);
			if(i==ei && j==ej)
			{
				val[get(si,sj)]+=v[ei][ej]-v[si][sj];
				val[get(ei,ej)]-=v[ei][ej];
				int r=(get(ei,ej)-1)*12+t[get(ei,ej)]+1;
				a[c[r][0]][c[r][1]]=a[ei][ej];
				c[a[ei][ej]][0]=c[r][0];
				c[a[ei][ej]][1]=c[r][1];
				a[ei][ej]=a[si][sj];
				c[a[ei][ej]][0]=ei;
				c[a[ei][ej]][1]=ej;
				a[si][sj]=0;
				return 1;
			}
			eat(si,sj,-1,0,i,j);
			if(i==ei && j==ej)
			{
				val[get(si,sj)]+=v[ei][ej]-v[si][sj];
				val[get(ei,ej)]-=v[ei][ej];
				int r=(get(ei,ej)-1)*12+t[get(ei,ej)]+1;
				a[c[r][0]][c[r][1]]=a[ei][ej];
				c[a[ei][ej]][0]=c[r][0];
				c[a[ei][ej]][1]=c[r][1];
				a[ei][ej]=a[si][sj];
				c[a[ei][ej]][0]=ei;
				c[a[ei][ej]][1]=ej;
				a[si][sj]=0;
				return 1;
			}
		}
	}
	t[get(ei,ej)]++;
	return 0;
}

Map::Map()
{
	//qDebug()<<"map";
	int i,j,r=1;val[0]=val[1]=val[2]=0;
	for(i=0;i<2;i++)
		for(j=0;j<6;j++)
		{
			c[r][0]=i;c[r][1]=j;
			a[i][j]=r++;
			val[1]+=v[i][j];
			ran[r-2]=r-2;
		}
	for(i=2;i<4;i++)
		for(j=0;j<6;j++)
			a[i][j]=0;
	for(i=4;i<6;i++)
		for(j=0;j<6;j++)
		{
			c[r][0]=i;c[r][1]=j;
			a[i][j]=r++;
			val[2]+=v[i][j];
		}
	//qDebug()<<"r="<<r;
	t[0]=t[1]=t[2]=12;
}
int Map::get(int i,int j)
{
	//qDebug()<<"get"<<(a[i][j]+11)/12;
	if(OVER(i) || OVER(j))
		return -1;
	return (a[i][j]+11)/12;
}
int Map::gett(int i)
{
	//qDebug()<<"gett";
	if(i>0 && i<3)
		return t[i];
	return -1;
}

void Map::eat(int si,int sj,int ri,int rj,int &ei,int &ej)
{
	//qDebug()<<"eat";
	int i=si,j=sj,t,di=ri,dj=rj;
	bool cr=0;
	do
	{
		i+=di;j+=dj;
		if(OVER(i) || OVER(j))
		{
			cr=1;
			i-=di;j-=dj;
			if((i<3 && j<3) || (i>2 && j>2))
			{
				t=i;i=j;j=t;t=-di;di=-dj;dj=t;
			}else
			{
				t=5-i;i=5-j;j=t;t=di;di=dj;dj=t;
			}
		}
	}while(a[i][j]==0 || (i==si && j==sj && (di!=ri || dj!=rj)));
	if(get(i,j)!=get(si,sj) && a[i][j]!=0 && cr)
	{
		ei=i;ej=j;
	}else
	{
		ei=ej=-1;
	}
}
Map::Map(const Map& b)
{
	//qDebug()<<"mapb";
	if(this == &b)
		return;
	/*int i,j;
	for(i=0;i<6;i++)
		for(j=0;j<6;j++)
				a[i][j]=b.a[i][j];
	for(i=1;i<=24;i++)
		c[i][0]=b.c[i][0],c[i][1]=b.c[i][1];
	t[0]=b.t[0],t[1]=b.t[1],t[2]=b.t[2];*/
	/*int i,j;
	for(i=0;i<6;i++)
		for(j=0;j<6;j++)
			a[i][j]=b.a[i][j];
	for(i=1;i<=24;i++)
		c[i][0]=b.c[i][0],c[i][1]=b.c[i][1];
	t[0]=b.t[0],t[1]=b.t[1],t[2]=b.t[2];*/
	memcpy(a,b.a,sizeof(int)*36);
	memcpy(c,b.c,sizeof(int)*50);
	memcpy(t,b.t,sizeof(int)*3);
	memcpy(val,b.val,sizeof(double)*3);
}
Map &Map::operator=(const Map &b)
{
//	qDebug()<<"ope=";
	if(this == &b) return *this;
	/*int i,j;
	for(i=0;i<6;i++)
		for(j=0;j<6;j++)
			a[i][j]=b.a[i][j];
	for(i=1;i<=24;i++)
		c[i][0]=b.c[i][0],c[i][1]=b.c[i][1];
	t[0]=b.t[0],t[1]=b.t[1],t[2]=b.t[2];*/
	memcpy(a,b.a,sizeof(int)*36);
	memcpy(c,b.c,sizeof(int)*50);
	memcpy(t,b.t,sizeof(int)*3);
	memcpy(val,b.val,sizeof(double)*3);
	return *this;
}
void Map::umove(int si,int sj,int ei,int ej,bool e)
{

	a[si][sj]=a[ei][ej];
	c[a[si][sj]][0]=si;c[a[si][sj]][1]=sj;
	val[get(si,sj)]-=v[ei][ej]-v[si][sj];
	if(e)
	{
		int r=(2-get(ei,ej))*12+t[3-get(ei,ej)]+1;
		c[r][0]=ei;c[r][1]=ej;
		//qDebug()<<"umove"<<r<<3-get(ei,ej)<<t[3-get(ei,ej)];
		t[3-get(ei,ej)]++;
		a[ei][ej]=r;
		val[get(ei,ej)]+=v[ei][ej];
	}
	else
		a[ei][ej]=0;
}
bool Map::getc(int k, bool b, int &i, int &j)
{
	if(k>=t[1+b]) return 0;
	int r=b*12+k+1;
	i=c[r][0];j=c[r][1];
	return 1;
}
double Map::getVal(int i)
{
	return val[i];
}
bool Map::getRandC(int k, bool b, int &i, int &j)
{

	if(k>=t[1+b])
	{
	//	qDebug()<<"over";
		ran[k-1]=k-1;
		return 0;
	}
	int n=rand()%(t[1+b]-k)+k;
	//qDebug()<<"r="<<ran[n];
	int r=b*12+ran[n]+1;
	ran[n]=ran[k];
	if(k>0)
		ran[k-1]=k-1;
	i=c[r][0];j=c[r][1];
	//for(n=k+1;n<12;n++)
		//qDebug()<<ran[n];
	return 1;
}
